﻿using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.Const;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Interaction;
using Kingdee.BOS.Core.List;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Core.Metadata.ConvertElement;
using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs;
using Kingdee.BOS.Orm;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using LM.YF.K3Cloud.Plugin.Models;
using LM.YF.K3Cloud.Plugin.Models.Grasses;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace LM.YF.K3Cloud.Plugin
{
    /// <summary>
    /// 运费结算操作服务插件
    /// <author>鹿奔</author>
    /// <date>240117</date>
    /// </summary>
    [Description("运费结算操作服务插件（挂载到货运单）：下推货运单到成本结算单（应付单）"), HotUpdate]
    public class FreightSettlementOperationServicePlugin : AbstractOperationServicePlugIn
    {
        #region MyRegion

        internal readonly ElementKeySchema Header_HuoYunDanHao = new ElementKeySchema
        {
            DbKey = "FBILLNO",
            FormKey = "FBillNo",
            OrmKey = "BillNo"
        };

        #endregion

        public override void OnPreparePropertys(PreparePropertysEventArgs e)
        {
            base.OnPreparePropertys(e);

            e.FieldKeys.Add(Header_HuoYunDanHao.FormKey);
        }

        public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e)
        {
            base.AfterExecuteOperationTransaction(e);

            // 运费结算，调用货运单->应付单单据转换

            const string sourceFormKey = "RDLV_DiliveOrder";// 货运单
            //const string ruleId1 = "5a27b083-1a40-405b-85ab-6e0206952a14";// 汇总下推货运单到应付单
            //const string ruleId2 = "5db4c921-1912-4c7a-bf36-b2513f5f5bee";// 进仓费结算下推货运单到应付单
            const string ruleId3 = "97952d76-d612-9c12-11ee-b4fd4363ba0b";// 一对一下推货运单到应付单
            var targetBillTypeId = DBUtils.ExecuteScalar<string>(Context, @"select top 1 a.FBILLTYPEID
                from T_BAS_BILLTYPE as a
                inner join T_BAS_BILLTYPE_L as b on b.FLOCALEID = 2052 and b.FBILLTYPEID = a.FBILLTYPEID
				where a.FBILLFORMID = 'AP_Payable' and b.FNAME = '发货运费应付单';", default);

            var rows = e.SelectedRows;
            var failureList = new List<string>();
            foreach (var row in rows)
            {
                var billId = row.DataEntity["Id"]?.ToString();
                var billNo = row.DataEntity[Header_HuoYunDanHao.OrmKey]?.ToString();
                var state = DBUtils.ExecuteScalar<string>(Context, $@"select FDOCUMENTSTATUS
                    from RDLV_t_DiliveOrder
                    where FID = {billId};", default);
                if (!"C".Equals(state))
                {
                    failureList.Add($"货运单【{billNo}】未审核，不允许结算运费。");
                    continue;
                }

                var entries = row.DataEntity["FEntity"] as DynamicObjectCollection;
                // 遍历货运单数据，获取源单内码和各分录内码
                var sourceIdList = new List<an11fva>();
                foreach (var entry in entries)
                {
                    var entryId = entry["Id"]?.ToString();

                    sourceIdList.Add(new an11fva
                    {
                        EntryId = entryId,
                        Id = billId,
                        BillNo = billNo
                    });
                }

                // 获取转换规则
                var convertRule = GetConvertRule(ruleId3);
                // 遍历源单
                var sourceIds = sourceIdList.Select(i => i.Id).Distinct();
                foreach (var sourceId in sourceIds)
                {
                    var sourceIdObjects = sourceIdList.Where(i => i.Id == sourceId);
                    var sourceBillNo = sourceIdObjects.First().BillNo;
                    var sourceEntries = new List<ListSelectedRow>();
                    for (int i = 0, l = sourceIdObjects.Count(); i < l; i++)
                    {
                        var sourceIdObject = sourceIdObjects.ElementAt(i);
                        var sourceEntry = new ListSelectedRow(sourceIdObject.Id, sourceIdObject.EntryId, i, sourceFormKey);
                        sourceEntry.EntryEntityKey = "FEntity"; //这里最容易忘记加，是重点的重点
                        //sourceEntry.BillNo = sourceIdObject.BillNo;
                        sourceEntries.Add(sourceEntry);
                    }

                    // 单据下推参数
                    PushArgs pushArgs = new PushArgs(convertRule, sourceEntries.ToArray());
                    //目标单据类型，必填参数，除非下游单据类型不是必填的，对源单数据进行过滤，给目标单赋值
                    pushArgs.TargetBillTypeId = targetBillTypeId;
                    // 目标单据主组织，可选参数，基础资料隔离，给没有主组织的目标数据包赋值，取当前登录组织即可
                    pushArgs.TargetOrgId = Context.CurrentOrganizationInfo.ID;

                    // 操作选项
                    OperateOption pushOption = OperateOption.Create();
                    pushOption.SetVariableValue(ConvertConst.SelectByBillId, false);
                    // 调用下推接口
                    var convertResult = ConvertServiceHelper.Push(Context, pushArgs, pushOption);

                    // 对转换结果进行处理
                    // 获取目标单据数据包
                    var targetObjs = (from p
                                      in convertResult.TargetDataEntities
                                      select p.DataEntity).ToArray();
                    // 为汇率赋值
                    foreach (var targetObj in targetObjs)
                    {
                        var finDataCollection = targetObj["AP_PAYABLEFIN"] as DynamicObjectCollection;
                        if (finDataCollection?.Count > 0)
                        {
                            foreach (var finData in finDataCollection)
                            {
                                var exchangeRate = Convert.ToSingle(finData["FExchangeRate"]);
                                if (exchangeRate == 0)
                                {
                                    finData["FExchangeRate"] = 1M;
                                }
                            }
                        }

                        var planDataCollection = targetObj["AP_PAYABLEPLAN"] as DynamicObjectCollection;
                        if (planDataCollection?.Count > 0)
                        {
                            foreach (var planData in planDataCollection)
                            {
                                var payRate = Convert.ToSingle(planData["FPAYRATE"]);
                                if (payRate == 0)
                                {
                                    planData["FPAYRATE"] = 100M;
                                }
                            }
                        }
                    }

                    var targetBInfo = GetBusinessInfo(pushArgs.ConvertRule.TargetFormId/*, pushArgs.ConvertRule.TargetFormMetadata*/);
                    // 直接调用保存接口，对数据进行保存
                    var failure = SaveTargetBill(targetBInfo, targetObjs);
                    if (failure != null)
                    {
                        failureList.Add($"货运单【{sourceBillNo}】下推的应付单保存失败：\r\n{failure}");
                    }
                }
            }
            if (failureList.Count > 0)
            {
                throw new KDBusinessException(null, string.Join("\r\n", failureList));
            }
        }

        /// <summary>
        /// 得到转换规则
        /// </summary>
        /// <param name="ruleId"></param>
        /// <returns></returns>
        private ConvertRuleElement GetConvertRule(string ruleId)
        {
            var convertRuleMeta = ConvertServiceHelper.GetConvertRule(Context, ruleId);
            return convertRuleMeta.Rule;
        }

        /// <summary>
        /// 保存目标单据
        /// </summary>
        private string SaveTargetBill(BusinessInfo targetBusinessInfo, DynamicObject[] targetBillObjs)
        {
            OperateOption saveOption = OperateOption.Create();
            saveOption.SetIgnoreWarning(true);
            saveOption.SetIgnoreInteractionFlag(true);
            var saveResult = BusinessDataServiceHelper.Save(Context, targetBusinessInfo, targetBillObjs, saveOption);
            if (!saveResult.IsSuccess)
            {
                var errorInfo = string.Join("\r\n", saveResult.ValidationErrors.Select(x => x.Message));
                return errorInfo;
            }

            return null;
        }

        /// <summary>
        /// 得到表单元数据
        /// </summary>
        /// <param name="formId"></param>
        /// <param name="metaData"></param>
        /// <returns></returns>
        private BusinessInfo GetBusinessInfo(string formId, FormMetadata metaData = null)
        {
            if (metaData != null)
            {
                return metaData.BusinessInfo;
            }
            metaData = FormMetaDataCache.GetCachedFormMetaData(Context, formId);
            return metaData.BusinessInfo;
        }
    }
}
